package com.game.springbootstart.controller.user;

import com.game.springbootstart.DTO.AdminDTO;
import com.game.springbootstart.DTO.LoginUser;
import com.game.springbootstart.VO.AdminVO;
import com.game.springbootstart.annotation.AutoFill;
import com.game.springbootstart.config.Result;
import com.game.springbootstart.constant.JwtClaimsConstant;
import com.game.springbootstart.entity.Admin;
import com.game.springbootstart.enumeration.OperationType;
import com.game.springbootstart.properties.JwtProperties;
import com.game.springbootstart.service.IAdminService;
import com.game.springbootstart.service.ILoginService;
import com.game.springbootstart.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.security.core.GrantedAuthority;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestController
public class LoginController {

    @Autowired
    private ILoginService loginService;

    private final AuthenticationManager authenticationManager;

    @Autowired
    private StringRedisTemplate redisTemplate;

    public LoginController(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }
    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private IAdminService adminService;

    @Autowired
    PasswordEncoder passwordEncoder;

//    @PostMapping("/login/login")
//    public Result login(@RequestBody AdminDTO adminDTO) {
//        UsernamePasswordAuthenticationToken authenticationToken =
//                new UsernamePasswordAuthenticationToken(adminDTO.getUsername(), adminDTO.getPassword());
//
//        // 认证
//        Authentication authentication = authenticationManager.authenticate(authenticationToken);
//        if(Objects.isNull(authentication)){
//            throw new RuntimeException("登录失败");
//        }
//        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
//        String userid = loginUser.getAdmin().getId().toString();
//        SecurityContextHolder.getContext().setAuthentication(authentication);
//
//        //登录成功后，生成jwt令牌
//        Map<String, Object> claims = new HashMap<>();
//        claims.put(JwtClaimsConstant.EMP_ID, userid);
//        claims.put(JwtClaimsConstant.SUBJECT, userid); // 添加 "subject" 为 userid
//        String token = JwtUtil.createJWT(
//                jwtProperties.getAdminSecretKey(),
//                jwtProperties.getAdminTtl(),
//                claims);
//
//        AdminVO adminVO = AdminVO.builder()
//                .id(loginUser.getAdmin().getId())
//                .userName(loginUser.getAdmin().getUsername())
//                .name(loginUser.getAdmin().getName())
//                .token(token)
//                .role(loginUser.getAdmin().getRole())
//                .imgUrl(loginUser.getAdmin().getImgUrl())
//                .build();
//        // 登录成功后返回 JWT 或用户信息
//        String key = "user_tokens_" + loginUser.getAdmin().getId();
//        redisTemplate.opsForHash().put(key, token, loginUser); // 存储 Token 和 LoginUser 的映射
//        return Result.success(adminVO);
//    }


    @PostMapping("/login/login")
    public Result login(@RequestBody AdminDTO adminDTO) {
        try {
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(adminDTO.getUsername(), adminDTO.getPassword());
            Authentication authentication = authenticationManager.authenticate(authenticationToken);
            if (Objects.isNull(authentication)) {
                return Result.fail();
            }
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
            String userId = loginUser.getAdmin().getId().toString();

            Map<String, Object> claims = new HashMap<>();
            claims.put(JwtClaimsConstant.EMP_ID, userId);
            claims.put(JwtClaimsConstant.SUBJECT, userId);
            claims.put("username", loginUser.getAdmin().getUsername());
            claims.put("role", loginUser.getAdmin().getRole());
            claims.put("authorities", loginUser.getAuthorities().stream()
                    .map(GrantedAuthority::getAuthority)
                    .collect(Collectors.toList()));

            String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(), jwtProperties.getAdminTtl(), claims);
//            System.out.println("Generated Token: " + token);

            AdminVO adminVO = AdminVO.builder()
                    .id(loginUser.getAdmin().getId())
                    .userName(loginUser.getAdmin().getUsername())
                    .name(loginUser.getAdmin().getName())
                    .token(token)
                    .role(loginUser.getAdmin().getRole())
                    .imgUrl(loginUser.getAdmin().getImgUrl())
                    .build();

            String key = "tokens_" + userId;
            redisTemplate.delete(key);
            redisTemplate.opsForValue().set(key, token,jwtProperties.getAdminTtl(), TimeUnit.SECONDS);
//            System.out.println("Stored Tokens in Redis: " + redisTemplate.opsForList().range(key, 0, -1));

            return Result.success(adminVO);
        } catch (AuthenticationException e) {
            return Result.fail();
        }
    }
    @GetMapping("login/logout")
    public Result logout() {
        loginService.logout();
        return Result.success(true);
    }

    @AutoFill(OperationType.INSERT)
    @PostMapping("login/save")
    public Result save(@RequestBody Admin admin) {
        String password = admin.getPassword();
        password = passwordEncoder.encode(password);
        admin.setPassword(password);
        admin.setRole("用户");
        return Result.success(adminService.save(admin));
    }
}
